package com.luzh.myspring.beans.factory.support;

import com.luzh.myspring.beans.BeanException;
import com.luzh.myspring.beans.factory.FactoryBean;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * FactoryBean注册表（支持从工厂获取对象）
 */
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
    //单例工厂的缓存
    private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>();

    /**
     * 从工厂缓存获取单例bean
     * @param beanName
     * @return
     */
    protected Object getCachedObjectForFactoryBean(String beanName) {
        Object object = factoryBeanObjectCache.get(beanName);
        return (object != NULL_OBJECT ? object : null);
    }

    /**
     * 从指定工厂获取对象
     * @param factory
     * @param beanName
     * @return
     */
    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName) {
        //单例工厂的对象需要缓存
        if (factory.isSingleton()) {
            Object object = factoryBeanObjectCache.get(beanName);
            if (object == null) {
                //从工厂创建对象
                object = doGetObjectFromFactoryBean(factory, beanName);
                //如果工厂中没有，缓存空对象
                this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
            }
            return (object != NULL_OBJECT ? object : null);
        } else {
            //原型工厂每次获取需要创建
            return doGetObjectFromFactoryBean(factory, beanName);
        }
    }

    /**
     * 直接调用工厂方法获取bean
     * @param factory
     * @param beanName
     * @return
     */
    private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName){
        try {
            return factory.getObject();
        } catch (Exception e) {
            throw new BeanException("FactoryBean threw exception on object [" + beanName + "] creation", e);
        }
    }

}

